/*
 * This file is part of gshot.
 *
 * Gshot is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Gshot is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with  this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Copyright (C) 2007-2011, Victor Ananjevsky <ananasik@gmail.com>
 */

#include "config.h"

#include <unistd.h>

#include "gshot.h"
#include "grabber.h"
#include "tray.h"
#include "callback.h"

void
capture_image (gint mode)
{
  gboolean state;
  gint cmode = mode;
  GtkWidget *win = GTK_WIDGET (gtk_builder_get_object (data.xml, "dialog"));

  /* Free previously captured image */
  if (data.image)
    g_object_unref (data.image);

  /* Hide window */
  state = gtk_widget_get_visible (win);
  if (data.hide && state)
    {
      gtk_widget_hide (win);
      /* wait for redrawing screen */
      while (gtk_events_pending ())
	gtk_main_iteration ();
    }

  /* sleep if needed */
  if (data.delay)
    {
      sleep (data.delay);
      while (gtk_events_pending ())
        gtk_main_iteration ();
    }
  
  /* Capture in the specified mode and store image in global data */
  if (data.image = capture (win, cmode, data.frame))
    {
      GdkPixbuf *p;
      gdouble factor;
      gdouble iw, ih;

      iw = gdk_pixbuf_get_width (data.image);
      ih = gdk_pixbuf_get_height (data.image);

      factor = MIN (350 / iw, 250 / ih);
      factor = (factor > 1.0) ? 1.0 : factor;

      if (p = gdk_pixbuf_scale_simple (data.image,
                                   iw * factor, ih * factor,
				       GDK_INTERP_BILINEAR))
        {
          gtk_image_set_from_pixbuf (GTK_IMAGE (gtk_builder_get_object
						(data.xml, "preview_image")), p);
          g_object_unref (p);
        }
    }

  /* Restore the window */
  if (state && data.hide)
    gtk_widget_show (win);
}

void
capture_screen (GtkWidget * w, gpointer d)
{
  capture_image (GRAB_SCREEN);
}

void
capture_window (GtkWidget * w, gpointer d)
{
  capture_image (GRAB_WINDOW);
}

void
capture_region (GtkWidget * w, gpointer d)
{
  capture_image (GRAB_REGION);
}

void
capture_mode (GtkWidget * w, gpointer d)
{
  capture_image (data.mode);
}

void
save_clicked (GtkWidget * w, gpointer d)
{
  GtkWidget *dlg;
  GtkFileFilter *filter;
  gchar *png_name, *jpeg_name, *bmp_name;
  static gchar *last_path = NULL;

  dlg = gtk_file_chooser_dialog_new (_("Save shot"),
                                     GTK_WINDOW (gtk_builder_get_object (data.xml, "dialog")),
                                     GTK_FILE_CHOOSER_ACTION_SAVE,
                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                     GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
                                     NULL);
  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dlg), TRUE);
  if (last_path)
    gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dlg), last_path);
  else
    gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dlg), data.folder);
  gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dlg), "screenshot.png");

  /* PNG filter */
  png_name = g_strdup (_("PNG image"));
  filter = gtk_file_filter_new ();
  gtk_file_filter_set_name (filter, png_name);
  gtk_file_filter_add_mime_type (filter, "image/png");
  gtk_file_filter_add_pattern (filter, "*.png");
  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), filter);

  /* JPEG filter */
  jpeg_name = g_strdup (_("JPEG image"));
  filter = gtk_file_filter_new ();
  gtk_file_filter_set_name (filter, jpeg_name);
  gtk_file_filter_add_mime_type (filter, "image/jpeg ");
  gtk_file_filter_add_pattern (filter, "*.jpg");
  gtk_file_filter_add_pattern (filter, "*.jpeg");
  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), filter);

  /* BMP filter */
  bmp_name = g_strdup (_("BMP image"));
  filter = gtk_file_filter_new ();
  gtk_file_filter_set_name (filter, bmp_name);
  gtk_file_filter_add_mime_type (filter, "image/bmp");
  gtk_file_filter_add_pattern (filter, "*.bmp");
  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), filter);

  if (gtk_dialog_run (GTK_DIALOG (dlg)) == GTK_RESPONSE_ACCEPT)
    {
      gchar *filename;

      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dlg));
      if (data.image)
        {
          const gchar *f_name;

          filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dlg));
          f_name = gtk_file_filter_get_name (filter);

          if (g_ascii_strcasecmp (f_name, png_name) == 0)
	    gdk_pixbuf_save (data.image, filename, "png", NULL,
			     "compression", "9", NULL);
          else if (g_ascii_strcasecmp (f_name, jpeg_name) == 0)
	    gdk_pixbuf_save (data.image, filename, "jpeg", NULL,
			     "quality", "100", NULL);
          else
	    gdk_pixbuf_save (data.image, filename, "bmp", NULL, NULL);
        }
      g_free (filename);
      
      /* save current folder */
      g_free (last_path);
      last_path = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dlg));
    }

  gtk_widget_destroy (dlg);

  g_free (png_name);
  g_free (jpeg_name);
  g_free (bmp_name);
}

void
open_in_cb (GtkWidget * w, gchar *cmd)
{
  gchar *filename, *str;
  static GRegex *rg = NULL;

  if (!data.image)
    return;

  /* save as temp */
  str = g_build_filename (g_getenv ("TMPDIR") ? g_getenv ("TMPDIR") : "/tmp", "gshot", NULL);
  g_mkdir_with_parents (str, 0755);
  filename = tempnam (str, "XXXXXXXX");
  g_free (str);
  
  gdk_pixbuf_save (data.image, filename, "png", NULL, "compression", "9", NULL);

  /* run command */
  if (!rg)
    rg = g_regex_new ("\%F", 0, 0, NULL);
  str = g_regex_replace_literal (rg, cmd, -1, 0, filename, 0, NULL);
  g_free (filename);

  g_spawn_command_line_async (str, NULL);
  g_free (str);
}

static void
menu_pos_cb (GtkMenu *m, gint *x, gint *y, gboolean *push_in, gpointer d)
{
  GtkWidget *w;
  GtkAllocation a;
  gint rx, ry;

  w = GTK_WIDGET (gtk_builder_get_object (data.xml, "open_button"));

  gdk_window_get_origin (gtk_widget_get_window (w), &rx, &ry);
  gtk_widget_get_allocation (w, &a);

  *x = rx + a.x;
  *y = ry + a.y + a.height;
  *push_in = TRUE;
}

void
open_clicked (GtkWidget *w, GdkEventButton *ev, gpointer d)
{
  if (ev->button == 1)
    {
      GtkWidget *m = create_open_menu ();
      gtk_menu_popup (GTK_MENU (m), NULL, NULL, menu_pos_cb, NULL, ev->button, ev->time);
    }
}

void
copy_clicked (GtkWidget * w, gpointer d)
{
  GtkClipboard *cb;

  cb = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
  gtk_clipboard_set_image (cb, data.image);
  gtk_clipboard_store (cb);
}

/* draw page for printing */
static void
draw_page (GtkPrintOperation * oper,
           GtkPrintContext * context,
           gint nr, gpointer d)
{
  cairo_t *cr;

  cr = gtk_print_context_get_cairo_context (context);

  if (data.image != NULL)
    {
      GdkPixbuf *pixbuf;
      guint iw, ih;
      gdouble pw, ph;

      /* scale image to page size */
      pw = gtk_page_setup_get_paper_width (data.page, GTK_UNIT_POINTS)
        - gtk_page_setup_get_left_margin (data.page, GTK_UNIT_POINTS)
        - gtk_page_setup_get_right_margin (data.page, GTK_UNIT_POINTS);
      ph = gtk_page_setup_get_paper_height (data.page, GTK_UNIT_POINTS)
        - gtk_page_setup_get_top_margin (data.page, GTK_UNIT_POINTS)
        - gtk_page_setup_get_bottom_margin (data.page, GTK_UNIT_POINTS);

      iw = gdk_pixbuf_get_width (data.image);
      ih = gdk_pixbuf_get_height (data.image);

      if (pw < iw || ph < ih)
        {
          gdouble factor;
          
          factor = MIN (pw / iw, ph / ih);
          factor = (factor > 1.0) ? 1.0 : factor;
          pixbuf = gdk_pixbuf_scale_simple (data.image,
                                            iw * factor, ih * factor,
                                            GDK_INTERP_HYPER);
        }
      else
        pixbuf = g_object_ref (data.image);

      /* add image to surface */
      gdk_cairo_set_source_pixbuf (cr, pixbuf, 0.0, 0.0);
      cairo_paint (cr);

      g_object_unref (pixbuf);
    }
}

void
print_clicked (GtkWidget * w, gpointer d)
{
  GtkPrintOperation *op;

  op = gtk_print_operation_new ();

  gtk_print_operation_set_n_pages (op, 1);
  gtk_print_operation_set_default_page_setup (op, data.page);
  if (data.print != NULL)
    gtk_print_operation_set_print_settings (op, data.print);

  g_signal_connect (G_OBJECT (op), "draw-page", G_CALLBACK (draw_page), NULL);

  if (gtk_print_operation_run (op, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
                               GTK_WINDOW (gtk_builder_get_object (data.xml, "dialog")),
			       NULL) == GTK_PRINT_OPERATION_RESULT_APPLY)
    {
      if (data.print != NULL)
       g_object_unref (data.print);
      data.print = g_object_ref (gtk_print_operation_get_print_settings (op));
    }

  g_object_unref (op);
}

void
set_folder (GtkFileChooser * f, gpointer d)
{
  g_free (data.folder);
  data.folder = gtk_file_chooser_get_current_folder (f);
}

void
set_delay (GtkRange * r, gpointer d)
{
  data.delay = (gint) gtk_range_get_value (r);
}

void
mode_changed (GtkWidget * w, gpointer d)
{
  data.mode = gtk_combo_box_get_active (GTK_COMBO_BOX (w));
}

void
frame_toggled (GtkWidget * w, gpointer d)
{
  data.frame = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
}

void
hide_toggled (GtkWidget * w, gpointer d)
{
  data.hide = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
}

void
tray_toggled (GtkWidget * w, gpointer d)
{
  data.tray = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
  if (data.tray)
    show_tray ();
  else
    hide_tray ();

  gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object (data.xml, "tray_hide_check")),
                            data.tray);
}

void
tray_hide_toggled (GtkWidget * w, gpointer d)
{
  data.tray_hide = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
}

void
exit_app (GtkWidget * w, gpointer d)
{
  if (data.tray)
    gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (data.xml, "dialog")));
  else
    gtk_main_quit ();
}

void
show_about (GtkWidget * w, gpointer d)
{
  const gchar *authors[] = {
    "Victor Ananjevsky <ananasik@gmail.com>",
    NULL
  };
  const gchar *translator = N_("translator name");

  gtk_show_about_dialog (GTK_WINDOW (gtk_builder_get_object (data.xml, "dialog")),
                         "name", PACKAGE,
                         "version", VERSION,
                         "authors", authors,
                         "copyright", _("(C) 2007-2011 Victor Ananjevsky <ananasik@gmail.com>"),
                         "comments", _("Application for capturing a snapshot of the entire screen,"
				       " a single window or user selected region"),
			 "logo-icon-name", "applets-screenshooter",
                         "translator-credits", _(translator),
			 "website", PACKAGE_URL,
                         NULL);
}

void 
cel_edit (GtkCellRendererText *cel, const gchar *path_str,
	  const gchar *text, gpointer d)
{
  gint col;
  GtkTreeIter iter;
  GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
  GtkTreeModel *model = GTK_TREE_MODEL (gtk_builder_get_object (data.xml, "scripts_store"));
    
  col = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cel), "col"));
  gtk_tree_model_get_iter (model, &iter, path);
  gtk_list_store_set (GTK_LIST_STORE (model), &iter, col, text, -1);
  gtk_tree_path_free (path);
}   

void
add_script (GtkWidget *w, gpointer d)
{
  GtkListStore *model;
  GtkTreeIter iter;

  model = GTK_LIST_STORE (gtk_builder_get_object (data.xml, "scripts_store"));
  gtk_list_store_append (model, &iter);
}

void
del_script (GtkWidget *w, gpointer d)
{
  GtkTreeIter iter;
  GtkListStore *model;
  GtkTreeSelection *sel;

  model = GTK_LIST_STORE (gtk_builder_get_object (data.xml, "scripts_store"));
  sel = gtk_tree_view_get_selection (GTK_TREE_VIEW 
				     (gtk_builder_get_object (data.xml, "scripts_list")));

  if (gtk_tree_selection_get_selected (sel, NULL, &iter))
    gtk_list_store_remove (model, &iter);
}
